﻿using System.Drawing;
using System.IO;

namespace PhoobearLibs.Media.Imaging.WBMP
{
    /// <summary>
    /// 비트맵을 WBMP형식으로 바꾸어 저장하는 클래스
    /// </summary>
    public sealed class WBMPBitmapEncoder
    {
        public WBMPBitmapEncoder()
        {

        }

        public bool Encode(string file, WBMPBitmap source)
        {
            //그레이스케일화
            try
            {
                using (FileStream fs = new FileStream(file, FileMode.Create))
                {
                    fs.WriteByte(0x00); // Type header 0
                    fs.WriteByte(0x00); // FixHeaderField

                    this.WriteMB(source.Size.Width, fs);  // Width
                    this.WriteMB(source.Size.Height, fs); // Height

                    this.EncodeData(fs, source); // Data                    
                }
                
                return true;
            }
            catch (System.Exception ex)
            {
                return false;
            }
        }


        private void EncodeData(Stream stream, WBMPBitmap source)
        {
            Size sz = source.Size;

            for (int row = 0; row < sz.Height; row++)
            {
                int bitposition = 8;
                byte octet = 0;
                for (int col = 0; col < sz.Width; col++)
                {
                    octet |= (byte)(((source.Bitmap[row * sz.Width + col] == false) ? 0 : 1) << --bitposition);
                    if (bitposition == 0)
                    {
                        bitposition = 8;
                        stream.WriteByte(octet);
                        octet = 0;
                    }
                }
                if (bitposition != 8)
                {
                    stream.WriteByte(octet);
                }
            }         
        }

        private void WriteMB(int i, Stream stream)
        {
            int count = 0;
            int accumulator = 0;

            while (accumulator != i)
            {
                accumulator += i & 0x7f << 7 * count++;                
            }

            for (int pos = count - 1; pos > 0; pos--)
            {
                byte mb = (byte)(0x80 | (pos & 0x7f << 7 * i) >> 7 * pos);
                stream.WriteByte(mb);
            }

            byte left = (byte)(i & 0x7f);
            stream.WriteByte(left);
        }
    }
}
